package br.com.foxinline.servico;

import br.com.foxinline.enums.Relatorio;
import br.com.foxinline.enums.TipoDocumento;
import br.com.foxinline.enums.TipoRequerimento;
import br.com.foxinline.generico.ServicoGenerico;
import br.com.foxinline.modelo.*;
import br.com.nordestefomento.jrimum.bopepo.BancoSuportado;
import br.com.nordestefomento.jrimum.bopepo.guia.Guia;
import br.com.nordestefomento.jrimum.bopepo.view.guia.GuiaViewer;
import br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.Agencia;
import br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.guia.*;
import br.com.nordestefomento.jrimum.utilix.ObjectUtil;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfImportedPage;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfWriter;
import java.awt.image.BufferedImage;
import java.beans.Transient;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.imageio.ImageIO;
import javax.persistence.Query;
import org.jrimum.bopepo.pdf.Files;
import org.jrimum.utilix.ClassLoaders;

/**
 *
 * @author elyjunior
 */
@Stateless
public class RequerimentoServico extends ServicoGenerico<Requerimento> {

    private Long quantidadeRegistrosResults;
    @EJB
    private PrefeituraServico prefeituraServico;

    public RequerimentoServico() {
        super(Requerimento.class);
    }
    
    
    public String documentosTipoRequerimento(Requerimento requerimento) {

        String texto = "";
        if (requerimento.getTipoRequerimento() == TipoRequerimento.AVERBACAO) {
            texto = "Documentos de Averbação";
        }
        if (requerimento.getTipoRequerimento() == TipoRequerimento.ITBI) {
            texto = "Documentos de ITBI";
        }
        if (requerimento.getTipoRequerimento() == TipoRequerimento.REVISAO_ALINHAMENTO) {
            texto = "Documentos de Revisao Alinhamento";
        }
        return texto;
    }

    public void imprimirRequerimento(Requerimento requerimento, HashMap parametros) {

        parametros.put("tipo_req", requerimento.getTipoRequerimento().getName());

        if (requerimento.getTipoDocumentoInteressado() == TipoDocumento.CPF) {
            parametros.put("cpf_cnpj_interessado", requerimento.getCpfInteressado());
            parametros.put("nome_interessado", requerimento.getNomeInteressado());
        }
        if (requerimento.getTipoDocumentoInteressado() == TipoDocumento.CNPJ) {
            parametros.put("cpf_cnpj_interessado", requerimento.getCnpjInteressado());
            parametros.put("nome_interessado", requerimento.getNomeFantasiaInteressado());
        }

        parametros.put("endereco_interessado", requerimento.getEnderecoInteressado());
        parametros.put("bairro_interessado", requerimento.getBairroInteressado());
        parametros.put("telefone_interessado", requerimento.getTelefoneInteressado());
        parametros.put("fax_interessado", requerimento.getFaxInteressado());
        parametros.put("cep_interessado", requerimento.getCepInteressado());
        parametros.put("n_interessado", requerimento.getNumInteressado());


        // Proprietário

        if (requerimento.getTipoDocumentoProprietario() == TipoDocumento.CPF) {
            parametros.put("cpf_cnpj_proprietario", requerimento.getCpfProprietario());
            parametros.put("nome_proprietario", requerimento.getNomeProprietario());
        }
        if (requerimento.getTipoDocumentoProprietario() == TipoDocumento.CNPJ) {
            parametros.put("cpf_cnpj_proprietario", requerimento.getCnpjProprietario());
            parametros.put("nome_proprietario", requerimento.getNomeFantasiaProprietario());
        }

        parametros.put("endereco_proprietario", requerimento.getEnderecoProprietario());
        parametros.put("bairro_proprietario", requerimento.getBairroProprietario());
        parametros.put("telefone_proprietario", requerimento.getTelefoneProprietario());
        parametros.put("fax_proprietario", requerimento.getFaxProprietario());
        parametros.put("cep_proprietario", requerimento.getCepProprietario());
        parametros.put("n_proprietario", requerimento.getNumProprietario());

        parametros.put("endereco_imovel", requerimento.getEnderecoImovel());
        parametros.put("bairro_imovel", requerimento.getBairroImovel());
        parametros.put("cep_imovel", requerimento.getCepImovel());
        parametros.put("n_imovel", requerimento.getNumImovel());

        RelatorioServico.genReport(parametros, null, Relatorio.REQUIREMENTO);
    }

    @Override
    public List<Requerimento> find(Requerimento requerimento, Integer first, Integer pageSize) {
        String select = "SELECT requerimento ";
        String sql = "FROM " + Requerimento.class.getSimpleName() + " requerimento ";
        String orderBy = " order by requerimento.id asc";

        sql += " where ";

        if (requerimento.getProcesso() != null && !requerimento.getProcesso().isEmpty()) {
            sql += " lower(requerimento.processo) like lower(:processo) and ";
        }


        if (requerimento.getNomeInteressado() != null && !requerimento.getNomeInteressado().isEmpty()) {
            sql += " lower(requerimento.nomeInteressado) like lower(:nomeInteressado) and ";
        }

        if (requerimento.getCpfInteressado() != null && !requerimento.getCpfInteressado().isEmpty()) {
            sql += " lower(requerimento.cpfInteressado) like lower(:cpfInteressado) and ";
        }

        if (requerimento.getNomeFantasiaInteressado() != null && !requerimento.getNomeFantasiaInteressado().isEmpty()) {
            sql += " lower(requerimento.nomeFantasiaInteressado) like lower(:nomeFantasiaInteressado) and ";
        }

        if (requerimento.getCnpjInteressado() != null && !requerimento.getCnpjInteressado().isEmpty()) {
            sql += " lower(requerimento.cnpjInteressado) like lower(:cnpjInteressado) and ";
        }


        if (requerimento.getNomeProprietario() != null && !requerimento.getNomeProprietario().isEmpty()) {
            sql += " lower(requerimento.nomeProprietario) like lower(:nomeProprietario) and ";
        }

        if (requerimento.getCpfProprietario() != null && !requerimento.getCpfProprietario().isEmpty()) {
            sql += " lower(requerimento.cpfProprietario) like lower(:cpfProprietario) and ";
        }

        if (requerimento.getNomeFantasiaProprietario() != null && !requerimento.getNomeFantasiaProprietario().isEmpty()) {
            sql += " lower(requerimento.nomeFantasiaProprietario) like lower(:nomeFantasiaProprietario) and ";
        }

        if (requerimento.getCnpjProprietario() != null && !requerimento.getCnpjProprietario().isEmpty()) {
            sql += " lower(requerimento.cnpjProprietario) like lower(:cnpjProprietario) and ";
        }


        sql += " requerimento.ativo = true ";

        Query query = getEntityManager().createQuery(select.concat(sql).concat(orderBy));

        setQuantidadeRegistros(sql, query, requerimento);

        setParameters(requerimento, query);

        query.setFirstResult(first).setMaxResults(pageSize);

        return query.getResultList();
    }

    private void setQuantidadeRegistros(String sql, Query query, Requerimento entidade) {

        String select = "SELECT count(requerimento) ";

        query = getEntityManager().createQuery(select + sql);

        setParameters(entidade, query);

        quantidadeRegistrosResults = (Long) query.getSingleResult();
    }

    @Transient
    private void setParameters(Requerimento entidade, Query query) {

        if (entidade.getProcesso() != null && !entidade.getProcesso().isEmpty()) {
            query.setParameter("processo", "%" + entidade.getProcesso() + "%");
        }
        if (entidade.getNomeInteressado() != null && !entidade.getNomeInteressado().isEmpty()) {
            query.setParameter("nomeInteressado", "%" + entidade.getNomeInteressado() + "%");
        }
        if (entidade.getCpfInteressado() != null && !entidade.getCpfInteressado().isEmpty()) {
            query.setParameter("cpfInteressado", "%" + entidade.getCpfInteressado() + "%");
        }
        if (entidade.getNomeFantasiaInteressado() != null && !entidade.getNomeFantasiaInteressado().isEmpty()) {
            query.setParameter("nomeFantasiaInteressado", "%" + entidade.getNomeInteressado() + "%");
        }
        if (entidade.getCnpjInteressado() != null && !entidade.getCnpjInteressado().isEmpty()) {
            query.setParameter("cnpjInteressado", "%" + entidade.getCnpjInteressado() + "%");
        }
        if (entidade.getNomeProprietario() != null && !entidade.getNomeProprietario().isEmpty()) {
            query.setParameter("nomeProprietario", "%" + entidade.getNomeProprietario() + "%");
        }
        if (entidade.getCpfProprietario() != null && !entidade.getCpfProprietario().isEmpty()) {
            query.setParameter("cpfProprietario", "%" + entidade.getCpfProprietario() + "%");
        }
        if (entidade.getNomeFantasiaProprietario() != null && !entidade.getNomeFantasiaProprietario().isEmpty()) {
            query.setParameter("nomeFantasiaProprietario", "%" + entidade.getNomeProprietario() + "%");
        }
        if (entidade.getCnpjProprietario() != null && !entidade.getCnpjProprietario().isEmpty()) {
            query.setParameter("cnpjProprietario", "%" + entidade.getCnpjProprietario() + "%");
        }
    }

    @Override
    public Long quantidadeRegistros() {
        return quantidadeRegistrosResults;
    }

    public void imprimirBoleto(Requerimento requerimento) throws IOException {

        List<Prefeitura> prefeituras = prefeituraServico.findAll();
        Prefeitura prefeitura = prefeituras.get(prefeituras.size() - 1);
        String agencia[] = prefeitura.getBancoAgencia().split("-");
        BufferedImage imageOrgaoRecebedor = null;
        if (prefeitura.getLogo() != null && prefeitura.getLogo().getUrl() != null && !prefeitura.getLogo().getUrl().isEmpty()) {
            imageOrgaoRecebedor = ImageIO.read(new File(prefeitura.getLogo().getUrl() + prefeitura.getLogo().getNome()));
        }

        /*
         * ====================================== Informando os dados do
         * contribuinte ======================================
         */

        String documento = requerimento.getTipoDocumentoInteressado().getTipo().equals(TipoDocumento.CPF.getTipo()) ? requerimento.getCpfInteressado() : requerimento.getCnpjInteressado();
        String nome = requerimento.getTipoDocumentoInteressado().getTipo().equals(TipoDocumento.CPF.getTipo()) ? requerimento.getNomeInteressado() : requerimento.getNomeFantasiaInteressado();

        br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.guia.Contribuinte contribuinte = new br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.guia.Contribuinte("NOME: " + nome, documento == null || documento.length() == 0 ? "00000000000" : documento);

        /*
         * ====================================== Informando os dados do
         * orgao/empresa recebedor ======================================
         */

        OrgaoRecebedor orgaoRecebedor = new OrgaoRecebedor(prefeitura.getNome(), TipoSeguimento.PREFEITURA);
        orgaoRecebedor.setCodigoDeIdentificacaoFebraban(new CodigoDeIdentificacaoFebraban(prefeitura.getCodigoFebraban()));
        // Se houver uma imagem(Ex: logo) do órgão recebedor...
        if (ObjectUtil.isNotNull(imageOrgaoRecebedor)) {
            orgaoRecebedor.setImgLogo(imageOrgaoRecebedor);
        }

        /*
         * ====================================== Informando os dados do
         * convênio ======================================
         */
        Convenio convenio = new Convenio();
        if (agencia.length == 2) {
            convenio.setAgencia(new Agencia(Integer.parseInt(agencia[0]), agencia[1]));
        }
        br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.Banco banco = BancoSuportado.BANCO_DO_BRASIL.create();
        br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.ContaBancaria contaB = new br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.ContaBancaria();
        contaB.setAgencia(new Agencia(Integer.parseInt(agencia[0]), agencia[1]));
        if (prefeitura.getBancoCarteira() != null) {
            br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.Carteira carteira = new br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.Carteira(Integer.parseInt(prefeitura.getBancoCarteira()), br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.TipoDeCobranca.COM_REGISTRO);
            contaB.setCarteira(carteira);
        }
        banco.addContaBancaria(contaB);
        convenio.setBanco(banco);
        convenio.setNumero(Integer.parseInt(prefeitura.getBancoNumeroConvenio()));

        /*
         * ====================================== Informando dados da
         * Arrecadação ======================================
         */
        Arrecadacao arrecadacao = new Arrecadacao(orgaoRecebedor, contribuinte, convenio);

        String nossoNumero = requerimento.getId() + "00";
        while (nossoNumero.length() < 14) {
            nossoNumero = "0" + nossoNumero;
        }

        //TODO Alterar Codigo Nosso Numero
        nossoNumero = "555" + nossoNumero;
        arrecadacao.setNossoNumero(nossoNumero);

        arrecadacao.setValorDocumento(requerimento.getCaixaRequerimento().getValor());
        arrecadacao.setTipoValorReferencia(TipoValorReferencia.QUANTIDADE_DE_MOEDA_COM_DV_MODULO_10);
        arrecadacao.setDataDoDocumento(GregorianCalendar.getInstance().getTime());
        File templatePersonalizado = new File(ClassLoaders.getResource("/br/com/foxinline/relatorio/iptu/MODELO_PARCELA_REQUERIMENTO.pdf").getFile());
        Calendar calendar = GregorianCalendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DAY_OF_MONTH, 2);
        arrecadacao.setDataDoVencimento(calendar.getTime());

        /*
         * ====================================== Informando dados da Guia
         * ======================================
         */

        Guia guia = new Guia(arrecadacao);

        guia.setInstrucaoAoCaixa1("PAGAMENTO SOMENTE À VISTA NO BANCO DO BRASIL.");
        guia.setInstrucaoAoCaixa2("PREFERENCIAMENTE DEVE SER PAGA NOS TERMINAIS DE AUTO-ATENDIMENTO,");
        guia.setInstrucaoAoCaixa3("CORRESPONDENTES BANCÁRIOS E INTERNET");

        // GuiaViewer é o responsável por prover uma visualização da guia.
        GuiaViewer guiaViewer = new GuiaViewer(guia);

        // Se houver um template personalizado, com campos extras, novas informações podem
        // ser adicionadas.
        if (ObjectUtil.isNotNull(templatePersonalizado)) {
            guia.addTextosExtras("txtValorDocumento2", "R$ " + arrecadacao.getValorDocumento().toString());
            guia.addTextosExtras("txtParcela", "UNICA");
            guia.addTextosExtras("txtParcela1", "UNICA");
            guia.addTextosExtras("txtNossoNumero", arrecadacao.getNossoNumero());
            guia.addTextosExtras("txtNossoNumero1", arrecadacao.getNossoNumero());
            guiaViewer = new GuiaViewer(guia);
            guiaViewer.setTemplate(templatePersonalizado);
        }


        // Gerando o arquivo. No caso o arquivo mencionado será salvo na mesma
        // pasta do projeto. Outros exemplos:
        // WINDOWS: boletoViewer.getAsPDF("C:/Temp/MeuBoleto.pdf");
        // LINUX: boletoViewer.getAsPDF("/home/temp/MeuBoleto.pdf");
        // File arquivoPdf = guiaViewer.getPdfAsFile("/opt/MinhaPrimeiraGuia.pdf");

        try {
            List<byte[]> boletosEmBytes = new ArrayList<byte[]>();
            boletosEmBytes.add(guiaViewer.getPdfAsByteArray());
            File arq = Files.bytesToFile("carneRequerimento.pdf", mergeFilesInPages(boletosEmBytes));
            RelatorioServico.genReport(Files.fileToBytes(arq));

            // Mostrando o boleto gerado na tela.
        } catch (DocumentException ex) {
            Logger.getLogger(RequerimentoServico.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(RequerimentoServico.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

     public void imprimirBoleto(Forus forus) throws IOException {

        List<Prefeitura> prefeituras = prefeituraServico.findAll();
        Prefeitura prefeitura = prefeituras.get(prefeituras.size() - 1);
        String agencia[] = prefeitura.getBancoAgencia().split("-");
        BufferedImage imageOrgaoRecebedor = null;
        if (prefeitura.getLogo() != null && prefeitura.getLogo().getUrl() != null && !prefeitura.getLogo().getUrl().isEmpty()) {
            imageOrgaoRecebedor = ImageIO.read(new File(prefeitura.getLogo().getUrl() + prefeitura.getLogo().getNome()));
        }

        /*
         * ====================================== Informando os dados do
         * contribuinte ======================================
         */

          String nome = forus.getAverbacao().getImovel().getProprietarios().get(0).getTipoDocumento().getTipo().equals(TipoDocumento.CPF.getTipo()) ? forus.getAverbacao().getImovel().getProprietarios().get(0).getNome() : forus.getAverbacao().getImovel().getProprietarios().get(0).getNomeFantasia();
          String documento = forus.getAverbacao().getImovel().getProprietarios().get(0).getTipoDocumento().getTipo().equals(TipoDocumento.CPF.getTipo()) ? forus.getAverbacao().getImovel().getProprietarios().get(0).getCpf() : forus.getAverbacao().getImovel().getProprietarios().get(0).getCnpj();

        br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.guia.Contribuinte contribuinte = new br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.guia.Contribuinte("NOME: " + nome, documento == null || documento.length() == 0 ? "00000000000" : documento);

        /*
         * ====================================== Informando os dados do
         * orgao/empresa recebedor ======================================
         */

        OrgaoRecebedor orgaoRecebedor = new OrgaoRecebedor(prefeitura.getNome(), TipoSeguimento.PREFEITURA);
        orgaoRecebedor.setCodigoDeIdentificacaoFebraban(new CodigoDeIdentificacaoFebraban(prefeitura.getCodigoFebraban()));
        // Se houver uma imagem(Ex: logo) do órgão recebedor...
        if (ObjectUtil.isNotNull(imageOrgaoRecebedor)) {
            orgaoRecebedor.setImgLogo(imageOrgaoRecebedor);
        }

        /*
         * ====================================== Informando os dados do
         * convênio ======================================
         */
        Convenio convenio = new Convenio();
        if (agencia.length == 2) {
            convenio.setAgencia(new Agencia(Integer.parseInt(agencia[0]), agencia[1]));
        }
        br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.Banco banco = BancoSuportado.BANCO_DO_BRASIL.create();
        br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.ContaBancaria contaB = new br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.ContaBancaria();
        contaB.setAgencia(new Agencia(Integer.parseInt(agencia[0]), agencia[1]));
        if (prefeitura.getBancoCarteira() != null) {
            br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.Carteira carteira = new br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.Carteira(Integer.parseInt(prefeitura.getBancoCarteira()), br.com.nordestefomento.jrimum.domkee.financeiro.banco.febraban.TipoDeCobranca.COM_REGISTRO);
            contaB.setCarteira(carteira);
        }
        banco.addContaBancaria(contaB);
        convenio.setBanco(banco);
        convenio.setNumero(Integer.parseInt(prefeitura.getBancoNumeroConvenio()));

        /*
         * ====================================== Informando dados da
         * Arrecadação ======================================
         */
        Arrecadacao arrecadacao = new Arrecadacao(orgaoRecebedor, contribuinte, convenio);

        String nossoNumero = forus.getId() + "00";
        while (nossoNumero.length() < 14) {
            nossoNumero = "0" + nossoNumero;
        }

        //TODO Alterar Codigo Nosso Numero
        nossoNumero = "555" + nossoNumero;
        arrecadacao.setNossoNumero(nossoNumero);

        arrecadacao.setValorDocumento(forus.getValor());
        arrecadacao.setTipoValorReferencia(TipoValorReferencia.QUANTIDADE_DE_MOEDA_COM_DV_MODULO_10);
        arrecadacao.setDataDoDocumento(GregorianCalendar.getInstance().getTime());
        File templatePersonalizado = new File(ClassLoaders.getResource("/br/com/foxinline/relatorio/iptu/MODELO_PARCELA_REQUERIMENTO.pdf").getFile());
        Calendar calendar = GregorianCalendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.DAY_OF_MONTH, 2);
        arrecadacao.setDataDoVencimento(calendar.getTime());

        /*
         * ====================================== Informando dados da Guia
         * ======================================
         */

        Guia guia = new Guia(arrecadacao);

        guia.setInstrucaoAoCaixa1("PAGAMENTO SOMENTE À VISTA NO BANCO DO BRASIL.");
        guia.setInstrucaoAoCaixa2("PREFERENCIAMENTE DEVE SER PAGA NOS TERMINAIS DE AUTO-ATENDIMENTO,");
        guia.setInstrucaoAoCaixa3("CORRESPONDENTES BANCÁRIOS E INTERNET");

        // GuiaViewer é o responsável por prover uma visualização da guia.
        GuiaViewer guiaViewer = new GuiaViewer(guia);

        // Se houver um template personalizado, com campos extras, novas informações podem
        // ser adicionadas.
        if (ObjectUtil.isNotNull(templatePersonalizado)) {
            guia.addTextosExtras("txtValorDocumento2", "R$ " + arrecadacao.getValorDocumento().toString());
            guia.addTextosExtras("txtParcela", "UNICA");
            guia.addTextosExtras("txtParcela1", "UNICA");
            guia.addTextosExtras("txtNossoNumero", arrecadacao.getNossoNumero());
            guia.addTextosExtras("txtNossoNumero1", arrecadacao.getNossoNumero());
            guiaViewer = new GuiaViewer(guia);
            guiaViewer.setTemplate(templatePersonalizado);
        }


        // Gerando o arquivo. No caso o arquivo mencionado será salvo na mesma
        // pasta do projeto. Outros exemplos:
        // WINDOWS: boletoViewer.getAsPDF("C:/Temp/MeuBoleto.pdf");
        // LINUX: boletoViewer.getAsPDF("/home/temp/MeuBoleto.pdf");
        // File arquivoPdf = guiaViewer.getPdfAsFile("/opt/MinhaPrimeiraGuia.pdf");

        try {
            List<byte[]> boletosEmBytes = new ArrayList<byte[]>();
            boletosEmBytes.add(guiaViewer.getPdfAsByteArray());
            File arq = Files.bytesToFile("carneRequerimento.pdf", mergeFilesInPages(boletosEmBytes));
            RelatorioServico.genReport(Files.fileToBytes(arq));

            // Mostrando o boleto gerado na tela.
        } catch (DocumentException ex) {
            Logger.getLogger(RequerimentoServico.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(RequerimentoServico.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
    
    
    
    
    
    
    public static byte[] mergeFilesInPages(List<byte[]> pdfFilesAsByteArray) throws DocumentException, IOException {

        Document document = new Document();
        ByteArrayOutputStream byteOS = new ByteArrayOutputStream();

        PdfWriter writer = PdfWriter.getInstance(document, byteOS);

        document.open();

        PdfContentByte cb = writer.getDirectContent();
        float positionAnterior = 0;



        //Para cada arquivo da lista, cria-se um PdfReader, responsável por ler o arquivo PDF e recuperar informações dele.
        for (byte[] pdfFile : pdfFilesAsByteArray) {

            PdfReader reader = new PdfReader(pdfFile);


            //Faz o processo de mesclagem por página do arquivo, começando pela de número 1.
            for (int i = 1; i <= reader.getNumberOfPages(); i++) {

                float documentHeight = cb.getPdfDocument().getPageSize().getHeight();

                //Importa a página do PDF de origem
                PdfImportedPage page = writer.getImportedPage(reader, i);
                positionAnterior = page.getHeight() * 4;
                float pagePosition = positionAnterior;

                /*
                 * Se a altura restante no documento de destino form menor que a
                 * altura do documento, cria-se uma nova página no documento de
                 * destino.
                 */
                if ((documentHeight - positionAnterior) <= page.getHeight()) {
                    document.newPage();
                    pagePosition = 0;
                    positionAnterior = 0;
                }

                //Adiciona a página ao PDF destino
                cb.addTemplate(page, 0, pagePosition);

                positionAnterior += page.getHeight();
            }
        }

        byteOS.flush();
        document.close();

        byte[] arquivoEmBytes = byteOS.toByteArray();
        byteOS.close();

        return arquivoEmBytes;
    }
}
